package com.xjd.edu.toolkit.helper;

import java.security.SecureRandom;
import java.util.Random;

/**
 * ID工具类
 *
 * @author wangyu
 * @created 2025/3/15 15:24
 */
public final class IdHelper {

    /**
     * 生成UUID字符串（单线程执行 100,000 次耗时不超过 70 毫秒）
     *
     * @return
     */
    public static String uuid() {
        return UUID.randomUUID().toString();
    }

    /**
     * UUID类（简化版）
     *
     * @see java.util.UUID
     */
    private static class UUID implements java.io.Serializable, Comparable<UUID> {

        private static final long serialVersionUID = -1L;

        private final long mostSigBits;
        private final long leastSigBits;

        private static class Holder {
            static final Random numberGenerator = new Random();
            static final Random secureNumberGenerator = new SecureRandom(); // 更安全的随机生成器（重复几率更低，性能相对较弱，暂未使用）
        }

        private UUID(byte[] data) {
            long msb = 0;
            long lsb = 0;
            assert data.length == 16 : "data must be 16 bytes in length";
            for (int i = 0; i < 8; i++)
                msb = (msb << 8) | (data[i] & 0xff);
            for (int i = 8; i < 16; i++)
                lsb = (lsb << 8) | (data[i] & 0xff);
            this.mostSigBits = msb;
            this.leastSigBits = lsb;
        }

        public UUID(long mostSigBits, long leastSigBits) {
            this.mostSigBits = mostSigBits;
            this.leastSigBits = leastSigBits;
        }

        public static UUID randomUUID() {
            Random ng = Holder.numberGenerator;

            byte[] randomBytes = new byte[16];
            ng.nextBytes(randomBytes);
            randomBytes[6] &= 0x0f;
            randomBytes[6] |= 0x40;
            randomBytes[8] &= 0x3f;
            randomBytes[8] |= 0x80;
            return new UUID(randomBytes);
        }

        public String toString() {
            return (digits(mostSigBits >> 32, 8) +
                    digits(mostSigBits >> 16, 4) +
                    digits(mostSigBits, 4) +
                    digits(leastSigBits >> 48, 4) +
                    digits(leastSigBits, 12));
        }

        private static String digits(long val, int digits) {
            long hi = 1L << (digits * 4);
            return Long.toHexString(hi | (val & (hi - 1))).substring(1);
        }

        public int hashCode() {
            long hilo = mostSigBits ^ leastSigBits;
            return ((int) (hilo >> 32)) ^ (int) hilo;
        }

        public boolean equals(Object obj) {
            if ((null == obj) || (obj.getClass() != UUID.class))
                return false;
            UUID id = (UUID) obj;
            return (mostSigBits == id.mostSigBits &&
                    leastSigBits == id.leastSigBits);
        }

        public int compareTo(UUID val) {
            return (this.mostSigBits < val.mostSigBits ? -1 :
                    (this.mostSigBits > val.mostSigBits ? 1 :
                            (Long.compare(this.leastSigBits, val.leastSigBits))));
        }
    }


}
